from django import forms
from django.contrib.auth import authenticate
from django.utils.encoding import force_unicode
from django.utils.html import conditional_escape
from django.utils.safestring import mark_safe
from django.forms.util import ErrorList

from django.contrib.auth.models import User
from shop.models import Address, UserProfile


MSG_VALIDATION_USERNAME_TAKEN = u'The username is already taken. Choose another one.'
MSG_VALIDATION_EMAIL_TAKEN = u'The email address is already in use. Choose another email address.'
MSG_VALIDATION_PASSWORD_MISMATCH = u'The passwords do not match. Please try again.'
MSG_VALIDATION_TOO_SHORT_PASSWORD = u'Password is too short. Minimum lenght is 3.'
MSG_VALIDATION_INVALID_PASSWORD = u'Password is invalid. Please try again.'


class ErrorLabel(ErrorList):
    """Renders field error messages inside a HTML label element, similarly as
    JQuery validation plugin.

    """
    def __unicode__(self):
        return self.as_label()

    def as_label(self):
        if not self: return u''
        messages = '. '.join([conditional_escape(force_unicode(e)) for e in self])
        return mark_safe(u'<label class="error">%s</label>' % messages)


class RegistrationForm(forms.Form):
    username = forms.CharField(max_length=30, min_length=3, label='User name')
    password = forms.CharField(widget=forms.PasswordInput, min_length=3)
    password2 = forms.CharField(widget=forms.PasswordInput, min_length=3,
                                label='Repeat Password')
    firstname = forms.CharField(max_length=30)
    lastname = forms.CharField(max_length=30)
    email = forms.EmailField(max_length=75)
    phonenumber = forms.CharField(max_length=15, label='Phone number')
    street_address = forms.CharField(max_length=255,
        widget=forms.Textarea(attrs={'cols': 40, 'rows': 3}))
    postal_code = forms.CharField(max_length=8, min_length=4)
    city = forms.CharField(max_length=50)
    country = forms.CharField(max_length=50)


    # validation functions

    def clean_username(self):
        username = self.cleaned_data['username']
        try:
            User.objects.get(username=username)
        except User.DoesNotExist:
            return username
        raise forms.ValidationError(MSG_VALIDATION_USERNAME_TAKEN)

    def clean_email(self):
        email = self.cleaned_data['email']
        try:
            User.objects.get(email=email)
        except User.DoesNotExist:
            return email
        raise forms.ValidationError(MSG_VALIDATION_EMAIL_TAKEN)

    def clean_password2(self):
        password = self.cleaned_data['password']
        password2 = self.cleaned_data['password2']
        if ('password' in self.cleaned_data and
            'password2' in self.cleaned_data and password != password2):
            raise forms.ValidationError(MSG_VALIDATION_PASSWORD_MISMATCH)
        return password2


    # user creation

    def register(self):
        data = self.cleaned_data

        user = User.objects.create_user(
                username=data['username'],
                email=data['email'],
                password=data['password'])
        user.first_name = data['firstname']
        user.last_name = data['lastname']
        user.save()

        address = Address.objects.create(
            name=user.get_full_name(),
            street_address=data['street_address'],
            postal_code=data['postal_code'],
            city=data['city'],
            country=data['country'])

        profile = UserProfile.objects.create(
                user=user,
                shipping_address=address,
                phonenumber=data['phonenumber'])
        profile.save()


class AccountForm(forms.Form):
    username = forms.CharField(max_length=30, min_length=3, label='User name')
    password = forms.CharField(widget=forms.PasswordInput, label='Current password')
    password2 = forms.CharField(widget=forms.PasswordInput, label='New password', required=False)
    password3 = forms.CharField(widget=forms.PasswordInput, label='Repeat password', required=False)
    firstname = forms.CharField(max_length=30)
    lastname = forms.CharField(max_length=30)
    email = forms.EmailField(max_length=75)
    phonenumber = forms.CharField(max_length=15, label='Phone number')
    street_address = forms.CharField(max_length=255,
        widget=forms.Textarea(attrs={'cols': 40, 'rows': 3}))
    postal_code = forms.CharField(max_length=8, min_length=4)
    city = forms.CharField(max_length=50)
    country = forms.CharField(max_length=50)

    def is_valid(self, request):
        self.user_profile = UserProfile.objects.get(user=request.user)
        return forms.Form.is_valid(self)

    # validation functions

    def clean_username(self):
        username = self.cleaned_data['username']
        if username != self.user_profile.user.username:
            try:
                User.objects.get(username=username)
            except User.DoesNotExist:
                return username
            raise forms.ValidationError(MSG_VALIDATION_USERNAME_TAKEN)
        return username

    def clean_email(self):
        email = self.cleaned_data['email']
        if email != self.user_profile.user.email:
            try:
                User.objects.get(email=email)
            except User.DoesNotExist:
                return email
            raise forms.ValidationError(MSG_VALIDATION_EMAIL_TAKEN)
        return email

    def clean_password(self):
        password = self.cleaned_data['password']
        username = self.user_profile.user.username
        user = authenticate(username=username, password=password)
        if user is not None:
            return password
        raise forms.ValidationError(MSG_VALIDATION_INVALID_PASSWORD)

    def clean_password3(self):
        password2 = self.cleaned_data['password2']
        password3 = self.cleaned_data['password3']

        # do not change password
        if(password2 == '' and password3 == ''):
            return '';

        if ('password2' in self.cleaned_data and len(password2) < 3):
            raise forms.ValidationError(MSG_VALIDATION_TOO_SHORT_PASSWORD)
        elif ('password2' in self.cleaned_data and
            'password3' in self.cleaned_data and password3 != password2):
            raise forms.ValidationError(MSG_VALIDATION_PASSWORD_MISMATCH)
        return password3



    # user update

    def update(self):
        data = self.cleaned_data

        if data['password3'] != '':
            self.user_profile.user.set_password(data['password3'])

        self.user_profile.user.username = data['username']
        self.user_profile.user.email = data['email']
        self.user_profile.user.first_name = data['firstname']
        self.user_profile.user.last_name = data['lastname']
        self.user_profile.user.save()

        self.user_profile.shipping_address.name = self.user_profile.user.get_full_name()
        self.user_profile.shipping_address.street_address = data['street_address']
        self.user_profile.shipping_address.postal_code = data['postal_code']
        self.user_profile.shipping_address.city = data['city']
        self.user_profile.shipping_address.country = data['country']
        self.user_profile.shipping_address.save()

        self.user_profile.phonenumber = data['phonenumber']
        self.user_profile.save()
